<script setup lang="ts" generic="T extends Record<string, any>">
import type { FormValidateCallback } from 'element-plus'
import type { DataFormProp } from './types'
import { computed, watch } from 'vue'
import { useForm } from '@/composables/useForm'

const { disabled, fields, cols, submit } = defineProps<DataFormProp<T>>()
const emits = defineEmits(['success', 'loadingChange'])

const formData = defineModel<T>({ required: true })

const { formRef, formLoading, submitForm, resetForm } = useForm(async () => {
  if (formData.value && submit) {
    const result = await submit(formData.value)
    emits('success', result)
    return result
  }
})

watch(() => formLoading.value, value => emits('loadingChange', value))

function validate(callback?: FormValidateCallback) {
  formRef.value?.validate(callback)
}
defineExpose({
  validate,
  formLoading,
  submitForm,
  resetForm,
})

const gridClass = computed(() => {
  const defaultClass = 'grid grid-cols-none'
  if (cols === 2) {
    return `${defaultClass} @2xl:grid-cols-2`
  }
  if (cols === 3) {
    return `${defaultClass} @2xl:grid-cols-2 @4xl:grid-cols-3`
  }

  if (cols === 4) {
    return `${defaultClass} @2xl:grid-cols-2 @5xl:grid-cols-3 @7xl:grid-cols-4`
  }

  return defaultClass
})
</script>

<template>
  <div class="@container">
    <el-form
      ref="formRef"
      :model="formData"
      label-width="auto"
      :disabled="disabled"
      :size="size ?? 'default'"
      status-icon
      :class="gridClass"
    >
      <template v-for="(item, index) in fields" :key="index">
        <data-field-item
          v-if="item.show === undefined || (typeof item.show === 'function' ? item.show(formData) : item.show) "
          v-model="(formData as any)[item.name]"
          :field="item" :data="formData"
        >
          <slot :name="item.name" :field="item" :data="formData" />
        </data-field-item>
      </template>
      <div v-if="$slots.append" class="flex items-center justify-end p-x-2 -col-end-1">
        <slot name="append" />
      </div>
    </el-form>
  </div>
</template>
